/*
 * @Author: xiaosihan
 * @Date: 2021-07-31 13:04:11
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2021-08-08 21:23:14
 */

import * as THREE from "three";
import { BufferGeometry, Camera, Group, Material, Scene, WebGLRenderer } from "three";
import { FullScreenQuad } from "three/examples/jsm/postprocessing/Pass";

/**
 * let lightColumn= new LightColumn("#f0f");
 * lightColumn.position.set(0, 0, 0);
 * lightColumn.scale.set(1, 1, 1);   
 * this.scene.add(lightColumn);     
 */
export default class LightColumn extends THREE.Object3D {

    constructor(color = "#fff") {
        super();
        this.init();
        this.setColor(color);
    }

    property = {
        color: "#fff"
    }

    cacheProperty = {
        color: "#fff"
    };

    // 后期修改颜色要调用这个方法
    setColor(color = "#fff") {
        this.property.color = color;
    }

    init() {
        this.add(this.sprite);
        this.sprite.position.set(0, 0, 0);
        this.sprite.material.map = this.spriteMap.texture;

        // 时时计算精灵模型的渲染顺序 距离相机近越近 渲染顺序就越大
        this.sprite.onBeforeRender = (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group) => {
            camera.getWorldPosition(LightColumn.cameraPosition);
            this.sprite.getWorldPosition(LightColumn.spritePosition);
            this.sprite.renderOrder = -LightColumn.cameraPosition.distanceTo(LightColumn.spritePosition);

            // 更新颜色
            // if (this.cacheProperty.color !== this.property.color) {
            this.cacheProperty.color = this.property.color;
            renderer.setRenderTarget(this.spriteMap);
            LightColumn.spriteShaderMaterial.uniforms.color.value.set(this.property.color);
            LightColumn.spriteShaderMaterial.uniforms.cameraPos.value.copy(LightColumn.cameraPosition);
            LightColumn.fsQuad.material = LightColumn.spriteShaderMaterial;
            LightColumn.fsQuad.render(renderer);
            renderer.setRenderTarget(null);
            // }


        }

    }

    sprite = new THREE.Sprite();

    // 点纹理
    spriteMap = (() => {
        let spriteMap = new THREE.WebGLRenderTarget(512, 512, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat });
        return spriteMap;
    })();

    static fsQuad = new FullScreenQuad(); // 渲染辅助器

    // 绘制点纹理的材质
    static spriteShaderMaterial = new THREE.ShaderMaterial({
        transparent: true,
        side: THREE.FrontSide,
        uniforms: {
            color: {
                value: new THREE.Color("#fff")
            },
            resolution: {
                value: new THREE.Vector2(1, 1)
            },
            cameraPos: {
                value: new THREE.Vector3(1, 1, 1)
            }
        },
        vertexShader: `
            varying vec3  vVertexWorldPosition;
            varying vec3  vVertexNormal;
            varying vec3 vPos;
            varying vec2 vUv;

            void main() {
                vUv = uv;
                vPos = position;
                //将法线转换到视图坐标系中
                vVertexNormal = normalize(normalMatrix * normal);
                //将顶点转换到世界坐标系中
                vVertexWorldPosition = (modelMatrix * vec4(position, 1.0)).xyz;

                gl_Position = vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            uniform vec2 resolution;
            uniform vec3 color;
            uniform vec3 cameraPos;
            varying vec2 vUv;
            varying vec3 vPos;

            varying vec3 vVertexNormal;
            varying vec3 vVertexWorldPosition;

            vec3 centerColor = vec3(1.0, 1.0, 1.0);
            vec2 centerPoint = vec2(0.5, 0.5);
            
            // 计算透明度
            float opacity(){
                
                // vec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition; //世界坐标系中从相机位置到顶点位置的距离
                // vec3 viewCameraToVertex = (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz; //视图坐标系中从相机位置到顶点位置的距离
                // viewCameraToVertex = normalize(viewCameraToVertex); //规一化
                // float intensity = distance( vec3(0.0, 1.0, 0.0), viewCameraToVertex);

                // centerPoint = normalize(normalize( cameraPosition - pos ));
                float intensity = distance( normalize(cameraPos - vVertexWorldPosition), vec3( 0.0, normalize(cameraPos - vVertexWorldPosition).y, 0.0 ) );
                
                float distanceX1 = abs(vUv.x - centerPoint.x) * 15.0;
                float distanceY1 = abs(vUv.y - centerPoint.y) * 15.0;

                float distanceX2 = abs(vUv.x - centerPoint.x) * 40.0;
                float distanceY2 = abs(vUv.y - centerPoint.y) * max(0.1, (1.0 - intensity)) * 30.0;

                float distance1 =  (1.0 - length( vec2( distanceX1, distanceY1 )));
                
                float distance2 =  ( 1.0 - length( vec2( distanceX2, distanceY2 )));

                if(vUv.y - centerPoint.y > 0.0){
                    distance2 = 0.0;
                }

                return 1.0;
                return  max( distance1, distance2);
            }

            // 计算片元颜色
            vec3 FragColor(){
                
                //世界坐标系中从相机位置到顶点位置的距离
                vec3 worldCameraToVertex = vVertexWorldPosition - cameraPosition; 

                //视图坐标系中从相机位置到顶点位置的距离
                vec3 viewCameraToVertex = (viewMatrix * vec4(worldCameraToVertex, 0.0)).xyz; 

                viewCameraToVertex = normalize(viewCameraToVertex); //规一化

                float intensity = distance( 
                    normalize(cameraPos - vPos), 
                    normalize( vec3( 0.0, cameraPos.y - vPos.y, 0.0 ) ) 
                );
                
                // centerPoint = normalize(  cameraPos ).xy;

                float distanceX1 = abs(vUv.x - centerPoint.x) * 30.0;
                float distanceY1 = abs(vUv.y - centerPoint.y) * 30.0;

                float distanceX2 = abs(vUv.x - centerPoint.x) * 100.0;
                float distanceY2 = abs(vUv.y - centerPoint.y) * max(0.1, (1.0 - intensity)) * 20.0;

                vec3 fragColor1 = vec3(1.0) * (1.0 - length( vec2( distanceX1, distanceY1 )));
                
                vec3 fragColor2 = vec3(1.0) * ( 1.0 - length( vec2( distanceX2, distanceY2 )));
                
                if(vUv.y - centerPoint.y > 0.0){
                    fragColor2 = vec3(0.0);
                }

                vec3 fragColor = clamp(fragColor1, 0.0, 1.0) + clamp(fragColor2, 0.0, 1.0);

                // return normalize(  cameraPosition );

                return clamp(fragColor, 0.0, 1.0) + color;
            }

            void main() {

                // if(cameraPosition.z == 0.0 ){
                //     discard;
                // }

                gl_FragColor = vec4( FragColor(), opacity() );

            }
        `
    });

    // 相机的位置
    static cameraPosition = new THREE.Vector3();

    // 精灵模型的位置
    static spritePosition = new THREE.Vector3();

}